package engine.logic.walk.Astar
{
	import engine.GameData;
	import engine.data.ModelLocator;
	import engine.flag.GameDefine;
	import engine.flag.PlayerActionFlag;
	import engine.logic.walk.WalkLogic;
	import engine.logic.walk.WalkManager;
	import engine.net.messages.CustomToServerFlag;
	import engine.net.mgr.SystemSender;
	import engine.newUi.ForbiddenAreaUI;
	import engine.newUi.NoticeUI;
	import engine.scene.SceneManager;
	import engine.scene.SceneView;
	import engine.scene.player.NpcModel;
	
	import flash.display.BlendMode;
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.events.MouseEvent;
	import flash.filters.GlowFilter;
	import flash.geom.Point;
	import flash.geom.Rectangle;
	import flash.utils.clearInterval;
	import flash.utils.setInterval;
	
	import newx.StageInfo;
	import newx.com.config.StaticIni;
	
	/**
	 * 禁地 
	 * @author gf
	 * 
	 */	
	
	public class ForbiddenAreaLogic
	{
		private static var self:ForbiddenAreaLogic;
		
		public var _cellSize:int	=	20;
		private var  _grid:Grid;
		private var _index:int;
		private var _path:Array;
		private var stepDis:Number	=	5;
		private var stepTime:int	=	30;
		public	 var stepIndex:int	=	-1;
		
		private var _sprite:Sprite;
		private var _back:Sprite;
		private var _mask:Sprite;
		private var _X:int;
		private var _Y:int;
		private var offX:int;
		private var offY:int;
		private var callBackFun:Function;
		private var forbiddenArea:Array	=	[];
		private var forbiddenWidth:int		=	1300;
		private var forbiddenHeight:int	=	760;
		
		private var gameScene:SceneView;
		
		private var sp:Sprite	=	new Sprite();
		
		public function ForbiddenAreaLogic()
		{
			init();
		}
		
		public static function getInstance():ForbiddenAreaLogic
		{
			if(self == null)
			{
				self = new ForbiddenAreaLogic();
			}
			return self;
		}
		
		private function init():void
		{
			gameScene	=	SceneManager.getInstance().norSceneView;
			addEvents();
		}
		
		private function addEvents():void
		{
			SceneManager.getInstance().norSceneView.addEventListener(MouseEvent.MOUSE_DOWN,onMouseDown);
		}
		
		private function onMouseDown(e:MouseEvent):void
		{
			try
			{
				if(WalkLogic.Fight) return;
				if(GameData.SceneType	==	GameDefine.SceneType_ForbiddenAreaScene)
				{
					if(ForbiddenAreaUI.getInstance().isAutoAddAction == 1)
					{
						if(ModelLocator.getInstance().scene.Role.GetProperties("MagicCoin") <5 && ForbiddenAreaUI.getInstance().currentAction == 0)
						{
							NoticeUI.getInstance().showInfo(StaticIni.getSwfLangStr("91808"));
							return;
						}
					}
					else if(ForbiddenAreaUI.getInstance().currentAction == 0)
					{
						NoticeUI.getInstance().showInfo(StaticIni.getSwfLangStr("ForbiddenAreaStr_10"));
						return;
					}
					
					var clickPoint : Point = new Point( gameScene.mouseX, gameScene.mouseY  );
					
					if(clickPoint.x < 0 || clickPoint.x >forbiddenWidth  || clickPoint.y < 0 || clickPoint.y >forbiddenHeight ) return;
					
					var EndPosX:int=Math.floor(clickPoint.x / _cellSize);
					var EndPosY:int=Math.floor(clickPoint.y / _cellSize);
					if(EndPosX < 0 || EndPosX > forbiddenWidth/_cellSize || EndPosY < 0 || EndPosY > forbiddenHeight/_cellSize) return;
					
					SystemSender.getInstance().CustomMsg(CustomToServerFlag.CLIENT_CUSTOMMSG_PLAYER_MOVETO, GameData.Role.point.x, GameData.Role.point.y, int(clickPoint.x), int(clickPoint.y));
					
					var clickPointStr:String	=	EndPosX+":"+EndPosY;
					if(forbiddenArea.length!=0)
					{
						if(forbiddenArea.indexOf(clickPointStr) != -1)
						{
							var maxNum:int				=	1000;
							var clickX:int				=	EndPosX;
							var clickY:int				=	EndPosY;
							
							var upCount:Object			=	{};
							var downCount:Object		=	{};
							var leftCount:Object		=	{};
							var rightCount:Object		=	{};
							var leftUpCount:Object		=	{};
							var rightUpCount:Object		=	{};
							var leftDownCount:Object	=	{};
							var rightDownCount:Object	=	{};
							
							while(_grid.getNode(EndPosX,EndPosY).walkable==false)
							{
								EndPosY--;
								if(EndPosY <= 0) break;
							}
							upCount["count"]		=	(EndPosY==0 ) ? maxNum : clickY-EndPosY ;
							upCount["point"]		=	new Point(EndPosX,EndPosY);
							EndPosY					=	clickY;
							
							while(_grid.getNode(EndPosX,EndPosY).walkable==false)
							{
								EndPosY++;
								if(EndPosY >= forbiddenHeight/_cellSize) break;
							}
							downCount["count"]	=	(EndPosY==forbiddenHeight/_cellSize)?maxNum:EndPosY	-	clickY;
							downCount["point"]		=	new Point(EndPosX,EndPosY);
							EndPosY		=	clickY;
							
							while(_grid.getNode(EndPosX,EndPosY).walkable==false)
							{
								EndPosX--;
								if(EndPosX <= 0) break;
							}
							leftCount["count"]	=	(EndPosX==0)?maxNum:clickX	-	EndPosX;
							leftCount["point"]		=	new Point(EndPosX,EndPosY);
							EndPosX		=	clickX;
							
							while(_grid.getNode(EndPosX,EndPosY).walkable==false)
							{
								EndPosX++;
								if(EndPosX >= forbiddenWidth/_cellSize) break;
							}
							rightCount["count"]	=	(EndPosX==forbiddenWidth/_cellSize)?maxNum:EndPosX	-	clickX;
							rightCount["point"]		=	new Point(EndPosX,EndPosY);
							EndPosX		=	clickX;
							
							while(_grid.getNode(EndPosX,EndPosY).walkable==false)
							{
								EndPosX--;
								EndPosY--;
								if(EndPosX <= 0 || EndPosY <= 0) break;
							}
							leftUpCount["count"]	=	(EndPosX==0||EndPosY==0)?maxNum:clickX	-	EndPosX;
							leftUpCount["point"]		=	new Point(EndPosX,EndPosY);
							EndPosX		=	clickX;
							EndPosY		=	clickY;
							
							while(_grid.getNode(EndPosX,EndPosY).walkable==false)
							{
								EndPosX++;
								EndPosY--;
								if(EndPosX >= forbiddenWidth/_cellSize || EndPosY <= 0) break;
							}
							rightUpCount["count"]=	(EndPosX==forbiddenWidth/_cellSize||EndPosY==0)?maxNum:EndPosX	-	clickX;
							rightUpCount["point"]		=	new Point(EndPosX,EndPosY);
							EndPosX		=	clickX;
							EndPosY		=	clickY;
							
							while(_grid.getNode(EndPosX,EndPosY).walkable==false)
							{
								EndPosX--;
								EndPosY++;
								if(EndPosX <= 0 || EndPosY >= forbiddenHeight/_cellSize) break;
							}
							leftDownCount["count"]=	(EndPosX==0||EndPosY==forbiddenHeight/_cellSize)?maxNum:clickX	-	EndPosX;
							leftDownCount["point"]		=	new Point(EndPosX,EndPosY);
							EndPosX		 =	clickX;
							EndPosY		 =	clickY;
							
							while(_grid.getNode(EndPosX,EndPosY).walkable==false)
							{
								EndPosX++;
								EndPosY++;
								if(EndPosX >= forbiddenWidth/_cellSize || EndPosY >= forbiddenHeight/_cellSize) break;
							}
							rightDownCount["count"]=	(EndPosX==forbiddenWidth/_cellSize||EndPosY==forbiddenHeight/_cellSize)?maxNum:EndPosX	-	clickX;
							rightDownCount["point"]		=	new Point(EndPosX,EndPosY);
							EndPosX		  =	clickX;
							EndPosY		  =	clickY;
							
							var sortArr:Array	=	[upCount,downCount,leftCount,rightCount,leftUpCount,leftDownCount,rightUpCount,rightDownCount];
							sortArr.sortOn("count",Array.NUMERIC);
							
							var index:int	=	-1;
							do
							{
								index++;
								var currentPoint:Point	=	sortArr[index]["point"] as Point;
								currentPoint	=	sortArr[index]["point"] as Point;
							}
							while( currentPoint.x<0 || currentPoint.x>forbiddenWidth/_cellSize ||
								currentPoint.y<0 || currentPoint.y>forbiddenHeight/_cellSize)
							
							
							EndPosX	=	(sortArr[index]["point"] as Point).x;
							EndPosY	=	(sortArr[index]["point"] as Point).y;
						}
					}
					
					var StartPosX:int=Math.floor(GameData.Role.x / _cellSize);
					var StartPosY:int=Math.floor(GameData.Role.y / _cellSize);
					
					var hasBarrier:Boolean = _grid.hasBarrier(StartPosX, StartPosY, EndPosX, EndPosY);
					if( hasBarrier )
					{
						startFindPath(StartPosX,StartPosY,EndPosX,EndPosY);
					}
					else
					{
						_path = [_grid.getNode(EndPosX, EndPosY)];
						_index = 0;
						clearInterval(stepIndex);
						stepIndex	=	setInterval(onEnterFrame,stepTime);
					}
					gameScene.showWalkIcon(new Point(EndPosX*_cellSize,EndPosY*_cellSize));
				}
			}
			catch(e:Error){}
		}
		
		public function startFindPath(startX:int,startY:int,endX:int,endY:int,callBack:Function=null):void
		{
			callBackFun	=	callBack;
			_grid.setEndNode(endX, endY);
			_grid.setStartNode(startX, startY);
			findPath();
		}
		
		public function forbiddenInit():void
		{
			_sprite				=	new Sprite();
			_back				=	new Sprite();
			_mask				=	new Sprite();
			
			_back.graphics.beginFill(0x00000);
			_back.graphics.drawRect(0,0,StageInfo.stage.width,StageInfo.stage.height);
			_back.graphics.endFill();
			_back.blendMode	=	BlendMode.LAYER;
			gameScene.addChild(_back);
			
			_sprite.graphics.beginFill(0x66ff33);
			_sprite.graphics.drawCircle(0,0,20);
			_sprite.graphics.endFill();
			_sprite.x	=	GameData.Role.x;
			_sprite.y	=	GameData.Role.y;
			_sprite.blendMode	=	BlendMode.ERASE;
			_sprite.filters	=	[new GlowFilter(0xffffff,1,30,30,10,1)];
			_back.addChild(_sprite);
			
			_mask.filters	=	[new GlowFilter(0xffffff,1,30,30,10,1)];
			_back.addChild(_mask);
			_mask.blendMode	=	BlendMode.ERASE;
		}
		
		
		public function makeGrid(forbiddenArr:Array=null):void
		{
			var width:int	=	int(2500/_cellSize);
			var height:int	=	int(750/_cellSize);
			_grid=new Grid(width, height);
			
			if(forbiddenArr==null) return;
			forbiddenArea	=	forbiddenArr;
			var length:int	=	forbiddenArr.length;
			for (var i:int=0; i < length; i++)
			{
				var pos:Array	=	(forbiddenArr[i] as String).split(":");
				_grid.setWalkable( pos[0],pos[1], false); 
			}
		}
		
		public function stopSearch():void
		{
			if(stepIndex != -1) clearInterval(stepIndex);
		}
		
		/** 画网格线以及为障碍物填充颜色*/
		private function drawGrid():void
		{
			sp.graphics.clear();
			for (var i:int=0; i < _grid.numCols; i++) 
			{ 
				for (var j:int=0; j < _grid.numRows; j++) 
				{ 
					var node:Node=_grid.getNode(i, j); 
					sp.graphics.lineStyle(0); 
					sp.graphics.beginFill(getColor(node),0.3); 
					sp.graphics.drawRect(i * _cellSize, j * _cellSize, _cellSize, _cellSize); 
				} 
			}
			gameScene.addChild(sp);
		}
		
		/** 返回节点颜色 */
		private function getColor(node:Node):uint
		{ 
			if (!node.walkable) return 0;
			return 0xffffff; 
		}
		
		private function findPath():void
		{ 
			var astar:AStar=new AStar(); 
			if (astar.findPath(_grid)) 
			{ 
				_path=astar.path; 
				_index=0;
				clearInterval(stepIndex);
				stepIndex	=	setInterval(onEnterFrame,stepTime);
			}
		}
		
		private function updateMask():void
		{
			if(_sprite.x != _X)
			{
				_sprite.x += offX;
			}
			if(_sprite.y != _Y)
			{
				_sprite.y += offY;
			}
			
			updateBack();
		}
		
		private function updateBack():void
		{
			_mask.graphics.beginFill(0x66ff33);
			_mask.graphics.drawCircle(_sprite.x,_sprite.y,20);
			_mask.graphics.endFill();
		}
		
		private function onEnterFrame(event:Event=null):void
		{
			if(WalkLogic.Fight)
			{
				clearInterval(stepIndex);
				GameData.Role.killMove();
				return;
			}
			if(_index >= _path.length) return;
			if(_path && _path.length !=0 )  GameData.Role.status	=	PlayerActionFlag.Run;
			
			//			updateMask();
			
			var targetX:Number=_path[_index].x * _cellSize + _cellSize / 2;
			var targetY:Number=_path[_index].y * _cellSize + _cellSize / 2;
			
			//			var passedNode:Node=_path[_index]; 
			//			sp.graphics.lineStyle(0); 
			//			sp.graphics.beginFill(0xffff00); 
			//			sp.graphics.drawRect(passedNode.x * _cellSize, passedNode.y * _cellSize, _cellSize, _cellSize); 
			
			var dx:Number=targetX - GameData.Role.x; 
			var dy:Number=targetY - GameData.Role.y;
			var radians : Number = Math.atan2(dy, dx);
			var dist:Number=Math.sqrt(dx * dx + dy * dy); 
			if (dist < stepDis) 
			{ 
				_index++;
				if (_index >= _path.length)
				{
					clearInterval(stepIndex);
					GameData.Role.status	= PlayerActionFlag.NormalWait;
					if(callBackFun!=null) callBackFun.call();
					callBackFun=null;
					gameScene.hideWalkIocn();
				} 
			} 
			else
			{
				GameData.Role.direction	= dx>=0 ? 1  : -1;
				var posX:Number	=	stepDis * Math.cos(radians);
				var posY:Number	=	stepDis * Math.sin(radians);
				
				
				GameData.Role.x += posX;
				GameData.Role.y += posY;
				
			}
			
			WalkManager.getInstance().walkLogic.changeDept();
		}
		
		public function getNPCWalkArea(val:NpcModel):Rectangle
		{
			var walkAreaStr:String	=	StaticIni.getIniVar("NpcWalkArea_"+GameData.SceneConfig,"walkArea");
			var walkAreaArr:Array	=	walkAreaStr.split("|");
			walkAreaArr.pop();
			var eachWalkArea:Array	=	[];
			var rect:Rectangle;
			var length:int			=	walkAreaArr.length;
			var x:int				=	val.getGuidePoint().x;
			var y:int				=	val.getGuidePoint().y;
			for(var i:int=0;i<length;i++)
			{
				eachWalkArea	=	(walkAreaArr[i] as String).split(",");
				if( x>=eachWalkArea[0]*_cellSize && x<=eachWalkArea[2]*_cellSize && y>=eachWalkArea[1]*_cellSize && y<=eachWalkArea[3]*_cellSize )
				{
					var walkX:int		=	(eachWalkArea[0])*_cellSize;
					var walkY:int		=	(eachWalkArea[1])*_cellSize;
					var width:int	=	(eachWalkArea[2]-eachWalkArea[0]+1)*_cellSize;
					var height:int	=	(eachWalkArea[3]-eachWalkArea[1]+1)*_cellSize;
					rect			=	new Rectangle( walkX,walkY,width,height );
					break;
				}
			}
			
			return rect;
		}
		
		
	}
}